package com.disk.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.disk.annotation.GlobalInterceptor;
import com.disk.annotation.VerifyParam;
import com.disk.config.AppConfig;
import com.disk.entity.constants.Constants;
import com.disk.entity.dto.CreateImageCode;
import com.disk.entity.dto.SessionWebUserDto;
import com.disk.entity.dto.UserSpaceDto;
import com.disk.entity.enums.VerifyRegexEnum;
import com.disk.entity.po.UserInfo;
import com.disk.entity.vo.ResponseVO;
import com.disk.exception.BusinessException;
import com.disk.service.EmailCodeService;
import com.disk.service.UserInfoService;
import com.disk.utils.RedisComponent;
import com.disk.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * <p>
 * 用户信息 前端控制器
 * </p>
 *
 * 处理用户相关的请求，包括注册、登录、验证码生成等功能。
 * @author zsy
 * @since 2024-08-06
 */
@RestController
public class UserController extends ABaseController {

    private static final Logger logger = LoggerFactory.getLogger(ABaseController.class);

    @Resource
    private EmailCodeService emailCodeService;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private AppConfig appConfig;

    @Resource
    private RedisComponent redisComponent;

    /**
     * 生成图片验证码
     *
     * @param response HttpServletResponse对象，用于设置响应的属性
     * @param session  HttpSession对象，用于存储验证码
     * @param type     验证码类型
     * @throws IOException 当发生IO错误时抛出
     */
    @RequestMapping("/checkCode")
    public void checkCode(HttpServletResponse response, HttpSession session, Integer type) throws IOException {
        CreateImageCode createImageCode = new CreateImageCode(138, 38, 5, 10);
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        String code = createImageCode.getCode();
        if (type == 0) {
            session.setAttribute(Constants.CHECK_CODE_KEY, code);
        } else {
            session.setAttribute(Constants.CHECK_CODE_KEY_EMAIL, code);
        }
        createImageCode.write(response.getOutputStream());
    }

    /**
     * 发送邮件验证码
     *
     * @param email    邮箱地址
     * @param checkCode 验证码
     * @param type     验证码类型
     * @param session  HttpSession对象，用于获取存储的验证码
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/sendEmailCode")
    @GlobalInterceptor(checkParams = true,checkLogin = false)
    public ResponseVO sendEmailCode(@VerifyParam(regex = VerifyRegexEnum.EMAIL, max = 150, required = true) String email,
                                    @VerifyParam(required = true) String checkCode,
                                    @VerifyParam(required = true) Integer type,
                                    HttpSession session) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
                throw new BusinessException("验证码错误");
            }
            emailCodeService.sendEmailCode(email, type);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL);
        }
    }

    /**
     * 用户注册
     *
     * @param email    邮箱地址
     * @param nickName 昵称
     * @param password 密码
     * @param checkCode 验证码
     * @param emailCode 邮箱验证码
     * @param session  HttpSession对象，用于获取存储的验证码
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/register")
    @GlobalInterceptor(checkParams = true,checkLogin = false)
    public ResponseVO register(@VerifyParam(regex = VerifyRegexEnum.EMAIL, max = 150, required = true) String email,
                               @VerifyParam(required = true, max = 20) String nickName,
                               @VerifyParam(regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18, required = true) String password,
                               @VerifyParam(required = true) String checkCode,
                               @VerifyParam(required = true) String emailCode,
                               HttpSession session) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("验证码错误");
            }
            userInfoService.register(email, nickName, password, emailCode);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 用户登录
     *
     * @param email    邮箱地址
     * @param password 密码
     * @param checkCode 验证码
     * @param session  HttpSession对象，用于获取存储的验证码
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/login")
    @GlobalInterceptor(checkParams = true,checkLogin = false)
    public ResponseVO login(@VerifyParam(regex = VerifyRegexEnum.EMAIL, max = 150, required = true) String email,
                            @VerifyParam(required = true) String password,
                            @VerifyParam(required = true) String checkCode,
                            HttpSession session) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("验证码错误");
            }
            SessionWebUserDto login = userInfoService.login(email, password);
            session.setAttribute(Constants.SESSION_KEY, login);
            return getSuccessResponseVO(login);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 重置密码
     *
     * @param email    邮箱地址
     * @param password 新密码
     * @param checkCode 验证码
     * @param emailCode 邮箱验证码
     * @param session  HttpSession对象，用于获取存储的验证码
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/resetPwd")
    @GlobalInterceptor(checkParams = true,checkLogin = false)
    public ResponseVO resetPwd(@VerifyParam(regex = VerifyRegexEnum.EMAIL, max = 150, required = true) String email,
                               @VerifyParam(regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18, required = true) String password,
                               @VerifyParam(required = true) String checkCode,
                               @VerifyParam(required = true) String emailCode,
                               HttpSession session) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("验证码错误");
            }
            userInfoService.resetPwd(email, password, emailCode);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 获取用户头像
     *
     * @param response HttpServletResponse对象，用于设置响应的属性
     * @param session  HttpSession对象，用于获取存储的用户信息
     * @param userId   用户ID
     */
    @RequestMapping("/getAvatar/{userId}")
    @GlobalInterceptor(checkParams = true,checkLogin = false)
    public void getAvatar(HttpServletResponse response,
                          HttpSession session,
                          @VerifyParam(required = true) @PathVariable(value = "userId") String userId) {
        try {
            String avatarFolderName = Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_AVATAR_NAME;
            File folder = new File(appConfig.getProjectFolder() + avatarFolderName);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            String avatarPath = appConfig.getProjectFolder() + avatarFolderName + userId + Constants.AVATAR_SUFFIX;
            File avatarFile = new File(avatarPath);
            if (!avatarFile.exists()) {
                if (!new File(appConfig.getProjectFolder() + avatarFolderName + Constants.AVATAR_DEFUALT).exists()) {
                    printNoDefaultImage(response);
                }
                avatarPath = appConfig.getProjectFolder() + avatarFolderName + Constants.AVATAR_DEFUALT;
            }
            response.setContentType("image/jpg");
            readFile(response, avatarPath);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 打印无默认图像信息
     *
     * @param response HttpServletResponse对象，用于设置响应的属性
     */
    private void printNoDefaultImage(HttpServletResponse response) {
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        response.setStatus(HttpStatus.OK.value());
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print("请在头像目录下放置默认头像default_avatar.jpg");
            writer.close();
        } catch (Exception e) {
            logger.error("输出无默认图失败", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 获取用户信息
     *
     * @param session HttpSession对象，用于获取存储的用户信息
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/getUserInfo")
    @GlobalInterceptor(checkParams = true)
    public ResponseVO getUserInfo(HttpSession session) {
        SessionWebUserDto sessionWebUserDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);
        return getSuccessResponseVO(sessionWebUserDto);
    }

    /**
     * 获取用户空间信息
     *
     * @param session HttpSession对象，用于获取存储的用户信息
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/getUseSpace")
    @GlobalInterceptor(checkParams = true)
    public ResponseVO getUserSpace(HttpSession session) {
        SessionWebUserDto sessionWebUserDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);
        UserSpaceDto userSpaceDto = redisComponent.getUserSpaceUse(sessionWebUserDto.getUserId());
        return getSuccessResponseVO(userSpaceDto);
    }

    /**
     * 用户注销
     *
     * @param session HttpSession对象，用于销毁会话
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/logout")
    public ResponseVO logout(HttpSession session) {
        session.invalidate();
        return getSuccessResponseVO(null);
    }

    /**
     * 更新用户头像
     *
     * @param session HttpSession对象，用于获取存储的用户信息
     * @param avatar  MultipartFile对象，用于接收上传的头像文件
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/updateUserAvatar")
    public ResponseVO updateUserAvatar(HttpSession session, MultipartFile avatar) {
        SessionWebUserDto sessionWebUserDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);
        String baseFolder = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE;
        File targetFileFolder = new File(baseFolder + Constants.FILE_FOLDER_AVATAR_NAME);
        if (!targetFileFolder.exists()) {
            targetFileFolder.mkdirs();
        }
        File targetFile = new File(targetFileFolder.getPath() + "/" + sessionWebUserDto.getUserId() + Constants.AVATAR_SUFFIX);
        try {
            avatar.transferTo(targetFile);
        } catch (Exception e) {
            logger.error("上传头像失败", e);
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setQqAvatar("");
        userInfoService.update(userInfo, new QueryWrapper<UserInfo>().eq("user_id", sessionWebUserDto.getUserId()));
        sessionWebUserDto.setAvatar(null);
        session.setAttribute(Constants.SESSION_KEY, sessionWebUserDto);
        return getSuccessResponseVO(null);
    }

    /**
     * 更新用户密码
     *
     * @param session  HttpSession对象，用于获取存储的用户信息
     * @param password 新密码
     * @return ResponseVO 响应对象
     */
    @RequestMapping("/updatePassword")
    @GlobalInterceptor(checkParams = true)
    public ResponseVO updatePassword(HttpSession session,
                                     @VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password) {
        SessionWebUserDto sessionWebUserDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);

        logger.info("更新密码，用户id：{}", sessionWebUserDto.getUserId());
        UserInfo userInfo = new UserInfo();
        userInfo.setPassword(StringTools.encodeByMd5(password));
        userInfoService.update(userInfo, new QueryWrapper<UserInfo>().eq("user_id", sessionWebUserDto.getUserId()));
        return getSuccessResponseVO(null);
    }
}
